
#include"Dictionary.h" 
#include "nlohmann/json.hpp"
#include "TcpConnection.h"
#include "KeyRecommander.h"

#include <iostream> 
#include <algorithm>
#include <iterator>
using std::set;
using std::cout;
using std::priority_queue;

KeyRecommander::KeyRecommander(string word,TcpConnectionPtr conn)
:_queryWord(word),
_conn(conn)
{
    execute();
}
//执行查询
void KeyRecommander::execute(){
    queryIndexTable();
    response();
}

MyResult::MyResult(int distance,int count,string word)
:_distance(distance),
_count(count),
_word(word)
{

}
void MyResult::print()const{
    cout<<"distance:"<<_distance<<" count:"<<_count<<" word:"<<_word<<"\n";
}
bool MyResult::operator<(const MyResult&rhs)const{
    if(_distance!=rhs._distance){
        return _distance>rhs._distance;
    }else{
        return _count<rhs._count;
    }
}
string MyResult::getWord()const{return _word;}





//遍历关键词拿到候选词索引set，根据set取候选词
void KeyRecommander::queryIndexTable(){
    //拿到索引表
    map<string,set<int>> indexTable=Dictionary::getInstance()->getIndexTable();
    vector<set<int>> keyIndexList;
    //遍历字符串
    for(size_t idx=0;idx<_queryWord.size();){
            string keyword;
            if((_queryWord[idx]&0x80)==0){
                keyword=_queryWord.substr(idx,1);
                ++idx;
            }else{
                size_t off=nByetesCode(_queryWord[idx]);
                keyword=_queryWord.substr(idx,off);
                idx+=off;
            }
            keyIndexList.push_back(indexTable[keyword]);
        }
    //keyIndexList中的set取并集
    set<int> totalIndex;
    totalIndex=getUnionSet(keyIndexList);
    //根据索引集合取出词
    vector<pair<string,int>> dict=Dictionary::getInstance()->getDict();
    vector<MyResult> myResultList;
    for(auto ele:totalIndex){
        dict[ele].first;
        distance(dict[ele].first);
        priMyResult.push(MyResult(distance(dict[ele].first),dict[ele].second,dict[ele].first));
    }




    
}
//计算编辑距离
int KeyRecommander::distance(const string rhs){
    int m = _queryWord.size();
    int n = rhs.size();

    // 创建 DP 表
    std::vector<std::vector<int>> dp(m + 1, std::vector<int>(n + 1, 0));

    // 初始化第一行和第一列
    for (int i = 0; i <= m; ++i) {
        dp[i][0] = i;  // 将 str1 的前 i 个字符转换为空字符串需要 i 次删除
    }
    for (int j = 0; j <= n; ++j) {
        dp[0][j] = j;  // 将空字符串转换为 str2 的前 j 个字符需要 j 次插入
    }

    // 填充 DP 表
    for (int i = 1; i <= m; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (_queryWord[i - 1] == rhs[j - 1]) {
                dp[i][j] = dp[i - 1][j - 1];  // 字符相等，不需要额外操作
            } else {
                dp[i][j] = 1 + std::min({
                    dp[i - 1][j],    // 删除
                    dp[i][j - 1],    // 插入
                    dp[i - 1][j - 1] // 替换
                });
            }
        }
    }

    // 返回结果
    return dp[m][n];
}
//set取并集
set<int> KeyRecommander::getUnionSet(vector<set<int>> &sets){
    if (sets.empty()) {
        return set<int>();;
    }
    set<int>result=sets[0];
    for (size_t i = 1; i < sets.size(); ++i) {
        result = unionOfSets(result, sets[i]);
    }
    return result;

}
set<int> KeyRecommander::unionOfSets(const set<int>& set1, const std::set<int>& set2) {
    set<int> result;
    set_union(set1.begin(), set1.end(), set2.begin(), set2.end(), inserter(result, result.begin()));
    return result;
}
size_t KeyRecommander::nByetesCode(const char ch){
    if(ch&(1<<7)){
        size_t nByetes=1;
        for(int idx=6;idx>0;--idx){
            if(ch&(1<<idx)){
                ++nByetes;
            }else{
                break;
            }
        }
        return nByetes;
    }
    return 1;
}
void KeyRecommander::response(){
    //弹出最多10个词然后序列化
    nlohmann::json json_array;
    int idx=0;
    while(idx<10&&!priMyResult.empty()){
        json_array[idx]=priMyResult.top().getWord();
        priMyResult.pop();
        idx++;
    }

    string dump= json_array.dump();
    cout<<dump<<"\n";

    _conn->sendInLoop(dump);
}
